Token-Based Authentication হল একটি জনপ্রিয় অথেন্টিকেশন মেথড যা সাধারণত ওয়েব অ্যাপ্লিকেশন বা মাইক্রোসার্ভিস আর্কিটেকচারে ব্যবহৃত হয়। এই মেথডে, ব্যবহারকারী তার লগইন তথ্য সফলভাবে প্রদান করার পরে একটি টোকেন পায়, যেটি পরবর্তী রিকোয়েস্টে প্রমাণীকরণের জন্য ব্যবহৃত হয়। এই টোকেনটি সাধারণত JWT (JSON Web Token) বা OAuth ভিত্তিক হতে পারে।
Stateless Session বলতে বোঝায় যে সার্ভার ক্লায়েন্টের সেশন সংরক্ষণ করে না। এর পরিবর্তে, প্রতিটি রিকোয়েস্টে ক্লায়েন্ট তার নিজস্ব অথেন্টিকেশন ইনফরমেশন (টোকেন) সহ রিকোয়েস্ট পাঠায় এবং সার্ভার শুধুমাত্র সেই তথ্য যাচাই করে অ্যাক্সেস অনুমতি দেয়।
Spring Security তে Token-Based Authentication এবং Stateless Session কনফিগার করার জন্য আমরা নিম্নলিখিত স্টেপগুলি অনুসরণ করব।
Step 1: Spring Security Configuration for Stateless Session
1.1: Spring Security Configuration Class তৈরি করুন
Spring Security তে Stateless সেশন কনফিগার করতে, আমরা HttpSecurity কনফিগারেশন এ sessionManagement() ব্যবহার করি এবং STATELESS হিসেবে কনফিগার করি। এর মানে হল যে সার্ভার কোনো সেশন তৈরি করবে না।
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable() // CSRF বন্ধ করা
.authorizeRequests()
.antMatchers("/auth/**").permitAll() // /auth endpoint গুলোর জন্য অ্যাক্সেস খোলা
.anyRequest().authenticated() // অন্য সকল রিকোয়েস্টের জন্য অথেন্টিকেশন প্রয়োজন
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS); // Stateless session
// JWT filter যোগ করা
http.addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
sessionCreationPolicy(SessionCreationPolicy.STATELESS): এটি সার্ভারকে বলছে যে কোনও সেশন সংরক্ষণ করা হবে না। সার্ভার প্রতিটি রিকোয়েস্টের সাথে নতুন অথেন্টিকেশন ভ্যালিডেশন করবে এবং সেশন তৈরি করবে না।- JWT Filter: যেহেতু আমরা Token-Based Authentication ব্যবহার করতে যাচ্ছি, আমাদের একটি JWT ফিল্টার প্রয়োজন যা প্রতিটি রিকোয়েস্টের Authorization হেডারে পাঠানো টোকেনটি যাচাই করবে।
Step 2: JWT Authentication Filter
Token-Based Authentication সাধারণত JWT (JSON Web Token) এর মাধ্যমে হয়। JWT টোকেনের সাহায্যে প্রতিটি HTTP রিকোয়েস্ট অথেন্টিকেট করা হয়। এটি সাধারণত একটি Authorization হেডারে পাঠানো হয়, উদাহরণস্বরূপ:
Authorization: Bearer <JWT_TOKEN>
2.1: JWT Authentication Filter
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(urlPatterns = "/api/*")
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private static final String TOKEN_PREFIX = "Bearer ";
private static final String HEADER_STRING = "Authorization";
private final JwtUtil jwtUtil; // JwtUtil একটি Utility ক্লাস যা টোকেন জেনারেট এবং ভ্যালিডেট করতে সাহায্য করবে
public JwtAuthenticationFilter(JwtUtil jwtUtil) {
this.jwtUtil = jwtUtil;
}
@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String header = request.getHeader(HEADER_STRING);
if (header == null || !header.startsWith(TOKEN_PREFIX)) {
chain.doFilter(request, response);
return;
}
String token = header.replace(TOKEN_PREFIX, "");
String username = jwtUtil.extractUsername(token);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
if (jwtUtil.validateToken(token, username)) {
Authentication authentication = new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
chain.doFilter(request, response);
}
}
- Authorization Header থেকে Token Extract করা: ফিল্টারটি HTTP হেডার থেকে
Authorizationটোকেন বের করে, এবং এটি যাচাই করে যদি টোকেনটি বৈধ হয় তবে Authentication কনটেক্সট সেট করে। jwtUtil.extractUsername(token): এই ফাংশনটি টোকেন থেকে ইউজারনেম বের করে।SecurityContextHolder.getContext().setAuthentication(authentication): এটি Spring Security কনটেক্সট এ সঠিক Authentication অবজেক্ট সেট করে।
Step 3: JWT Utility Class
JWT Utility ক্লাসটি টোকেন জেনারেট এবং ভ্যালিডেশন করার জন্য ব্যবহার করা হবে।
3.1: JwtUtil Class
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.Claims;
import java.util.Date;
public class JwtUtil {
private static final String SECRET_KEY = "secretKey"; // নিজের SECRET_KEY ব্যবহার করুন
// টোকেন জেনারেট করা
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60)) // 1 hour
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
// টোকেন থেকে ইউজার নাম বের করা
public String extractUsername(String token) {
return extractClaims(token).getSubject();
}
// টোকেন থেকে তথ্য বের করা
private Claims extractClaims(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
}
// টোকেন ভ্যালিডেশন
public boolean validateToken(String token, String username) {
return (username.equals(extractUsername(token)) && !isTokenExpired(token));
}
// টোকেনের মেয়াদ শেষ হয়েছে কিনা
private boolean isTokenExpired(String token) {
Date expiration = extractClaims(token).getExpiration();
return expiration.before(new Date());
}
}
generateToken(): এই ফাংশনটি ইউজারনেমের সাথে একটি JWT টোকেন তৈরি করে।extractUsername(): টোকেন থেকে ইউজারনেম বের করার জন্য ব্যবহৃত হয়।validateToken(): টোকেনটি ভ্যালিড কিনা যাচাই করে।isTokenExpired(): টোকেনের মেয়াদ শেষ হয়েছে কিনা যাচাই করে।
Step 4: Token-Based Authentication Flow
- User Login: ব্যবহারকারী তার ইউজারনেম এবং পাসওয়ার্ড দিয়ে লগইন করে।
- Generate JWT Token: লগইন সফল হলে সার্ভার একটি JWT টোকেন জেনারেট করে এবং ক্লায়েন্টকে প্রদান করে।
- Token Validation: ক্লায়েন্ট পরবর্তী রিকোয়েস্টের সাথে JWT টোকেন পাঠায়। সার্ভার
JwtAuthenticationFilterএর মাধ্যমে টোকেন যাচাই করে এবং যদি টোকেনটি বৈধ হয়, তবে ব্যবহারকারীকে অথেন্টিকেট করে।
উপসংহার
Token-Based Authentication এবং Stateless Session Spring Security-তে খুবই গুরুত্বপূর্ণ একটি সিকিউরিটি প্যাটার্ন, যা আধুনিক ওয়েব অ্যাপ্লিকেশন ও মাইক্রোসার্ভিস আর্কিটেকচারে ব্যবহৃত হয়। এখানে, JWT ভিত্তিক অথেন্টিকেশন সেটআপ করতে JwtAuthenticationFilter, JwtUtil, এবং SecurityConfig কনফিগারেশন তৈরি করা হয়েছে। Stateless সেশন ব্যবহারের মাধ্যমে সার্ভার কোন সেশন ম্যানেজমেন্ট না করে, প্রতিটি রিকোয়েস্টের সাথে টোকেন যাচাই করে।
Read more